package com.bzgwl.mybatis_plus.config;

import com.bzgwl.mybatis_plus.security.MyAuthenticationProvider;
import com.bzgwl.mybatis_plus.security.MySecurityFilter;
import com.bzgwl.mybatis_plus.security.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

/**
 * Author: Professor_Kong
 * date: 2018/6/8

 * @EnableGlobalMethodSecurity(securedEnabled=true)
 * 开启@Secured 注解过滤权限
 * @EnableGlobalMethodSecurity(jsr250Enabled=true)
 * 开启@RolesAllowed 注解过滤权限
 * @EnableGlobalMethodSecurity(prePostEnabled=true)
 *  -@PreAuthorize 在方法调用之前,基于表达式的计算结果来限制对方法的访问
 *  -@PostAuthorize 允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常
 *  -@PostFilter 允许方法调用,但必须按照表达式来过滤方法的结果
 *  -@PreFilter 允许方法调用,但必须在进入方法之前过滤输入值
 */

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启security注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAuthenticationProvider authenticationProvider;

    @Autowired
    @Qualifier("mySecurityFilter")
    private MySecurityFilter mySecurityFilter;

    @Autowired
    @Qualifier("myUserDetailsService")
    private UserDetailsService myUserDetailsService;

//    @Bean
//    UserDetailsService myUserDetailsService(){
//        return  new MyUserDetailsService();
//    }

//    @Autowired
//    private JWTAuthenticationFilter jwtAuthenticationFilter;


    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //允许所有用户访问"/"和"/home"
        http

                .csrf().disable()      //（Cross-site request forgery）跨站请求伪造
                .authorizeRequests()   //授权请求
                .antMatchers("/static/**",
                        "/static/**/**", "/favicon.ico","/static/**/**/**").permitAll()
                .antMatchers("/","/login","/websocket").permitAll()//访问：/home 无需登录认证权限
                .anyRequest().authenticated()//其他所有资源都需要认证，登陆后访问
                .and().headers().frameOptions().disable() //解决X-Frame-Options deny 造成的页面空白
                .and()
                .formLogin()
                //指定登录页是"/login"
                .loginPage("/login")          //自定义登录页url,默认为/login
//                .loginProcessingUrl("/login")    //登录请求拦截的url,也就是form表单提交时指定的action
                .defaultSuccessUrl("/index")
                .failureUrl("/login?error")
                .permitAll()
                //.successHandler(loginSuccessHandler())//code3
                .and()
                .logout()
                .logoutSuccessUrl("/")//退出登录后的默认url是"/"
                .permitAll()
                .and()
                .exceptionHandling()
//                .accessDeniedHandler()
                .accessDeniedPage("/403")  //无权限处理
                .and()
                .rememberMe()//登录后记住用户，下次自动登录,数据库中必须存在名为persistent_logins的表
                    .tokenValiditySeconds(1209600)
                .and()
//                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
                .addFilterBefore(mySecurityFilter, FilterSecurityInterceptor.class);//在正确的位置添加我们自定义的过滤器;  ;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService);
        auth.authenticationProvider(authenticationProvider);
//                .passwordEncoder(passwordEncoder());
    }
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**").antMatchers("/static/**");
        //可以仿照上面一句忽略静态资源
    }


    /**
     * 设置用户密码的加密方式为MD5加密
     * @return
     */
//    @Bean
//    public Md5PasswordEncoder passwordEncoder() {
//        return new Md5PasswordEncoder();
//    }
}
